#ifndef __COMM_HPP__
#define __COMM_HPP__


#include<iostream>
#include<cerrno>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<assert.h>
#include<unistd.h>
//路劲就设置为当前路径
#define PATHNAME "."
//项目ID
#define PROJID 0x6666
#define SIZE 4096
key_t getKey()
{
  //这个函数用于获取一个key值
  key_t k = ftok(PATHNAME,PROJID);
  if(k == -1)
  {
    //出错了
    std::cerr<<"error:"<<errno<<strerror(errno)<<std::endl;
    exit(1);
  }
  return k;
}
static int createShmHelper(key_t k,int size,int flag)
{
  int shmid= shmget(k,size,flag);
  if(shmid==-1)
  {
   //创建失败
   std::cerr<<"error:"<<errno<<strerror(errno)<<std::endl;
   exit(2);
  }
  return shmid;
}
int createShm(key_t k,int size)
{
  umask(0);
  return createShmHelper(k,size,IPC_CREAT|IPC_EXCL|0666);
}
int getShm(key_t k,int size)
{
  return createShmHelper(k,size,IPC_CREAT);
}
char* linkShm(int shmid)
{
  //第三个参数意思是如果指定了SHM_RDONLY则以只读方式链接，否则就是默认读写
  char* startAddr = (char*)shmat(shmid,nullptr,0);
  return startAddr;
}
void detachShm(char* startAddr)
{
  //断开链接
  int n = shmdt(startAddr);
  assert(n!=-1);
  (void)n;
}
void delShm(int shmid)
{
  int n = shmctl(shmid,IPC_RMID,nullptr);
  assert(n!=-1);
  (void)n;
}
#define SERVER 1
#define CLIENT 0
class Init
{
  public:
    Init(int t)
      :type(t)
  {
    key_t k = getKey();
    if(type == SERVER)
    {
      shmid = createShm(k,SIZE);
    }
    else
    {
      shmid = getShm(k,SIZE);
    }
    start = linkShm(shmid);
  }
    char* getStart()
    {
      return start;
    }
  ~Init()
  {
    detachShm(start);
    if(type == SERVER)
    {
      delShm(shmid);
    }
  }
private:
    char* start;
    int type;//server or client
    int shmid;
};
#endif
